package com.asura.qqeffect.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * Created by Asura on 2016/9/14.
 */
public class SlidingMenu extends ViewGroup {
    private static final String TAG = "SlidingMenu";
    private View menu;
    private View content;
    private int menuHeight;
    private int width;
    private int contentHeight;
    private Scroller scroller;
    private OnSlidingListener listener;
    private int touchSlop;
    private VelocityTracker velocityTracker;
    private int maximumFlingVelocity;
    private int minimumFlingVelocity;


    public SlidingMenu(Context context) {
        this(context, null);
    }

    public SlidingMenu(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        menu.layout(0, 0, width, menuHeight);
        content.layout(0, menuHeight, width, menuHeight + contentHeight);
        if (changed) {
            scrollTo(0, menuHeight);
        }
    }

    private void init(Context context) {
        scroller = new Scroller(context);
//        scroller = new Scroller(context,new OvershootInterpolator());
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        velocityTracker = VelocityTracker.obtain();
        ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
        maximumFlingVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
        minimumFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
        Log.i("TAG", maximumFlingVelocity + "&" + minimumFlingVelocity);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            postInvalidate();
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        menu = getChildAt(0);
        content = getChildAt(1);
    }

    public void setOnSlidingListener(OnSlidingListener listener) {
        this.listener = listener;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        width = MeasureSpec.getSize(widthMeasureSpec);
        int height = 0;
        for (int i = 0, len = getChildCount(); i < len; i++) {
            measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
            height += getChildAt(i).getMeasuredHeight();
        }
        menuHeight = menu.getMeasuredHeight();
        contentHeight = content.getMeasuredHeight();
        setMeasuredDimension(width, height);
    }


    int downY;
    int dY = 0;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        velocityTracker.addMovement(event);
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                dY = y - downY;
                int scrollY = getScrollY();
                if (dY > 0) {
                    //向下
                    if (scrollY > 0) {//上界
                        if (dY - scrollY >= 0) {
                            dY = 0;
                        }
                        scrollBy(0, -dY);
                        if (listener != null) {
                            listener.onSliding((menuHeight - scrollY) * 1.0f / menuHeight);
                        }
                    }
                } else {
                    //向上
                    if (scrollY < menuHeight) {//下边界
                        if (scrollY - dY >= menuHeight) {
                            dY = scrollY - menuHeight;
                        }
                        scrollBy(0, -dY);
                        if (listener != null) {
                            listener.onSliding((menuHeight - scrollY) * 1.0f / menuHeight);
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                velocityTracker.computeCurrentVelocity(1000);
                int yVelocity = (int) Math.abs(velocityTracker.getYVelocity());
                Log.i("TAG",velocityTracker.getYVelocity()+"");
                if (yVelocity > minimumFlingVelocity && yVelocity < maximumFlingVelocity) {
                    int sy = getScrollY();
                    if(dY > 0) {
                        scroller.startScroll(0, sy, 0, -sy, 500);
                        invalidate();
                    }else {
                        scroller.startScroll(0, sy, 0, menuHeight - sy, 500);
                        invalidate();
                    }
                } else {
                    int sy = getScrollY();
                    if (sy > menuHeight / 2) {
                        //回弹
                        scroller.startScroll(0, sy, 0, menuHeight - sy, 500);
                        invalidate();
                        if (listener != null) {
                            listener.onSliding(0);
                        }
                    } else if (sy > 0) {
                        //显示出来
                        scroller.startScroll(0, sy, 0, -sy, 500);
                        invalidate();
                        if (listener != null) {
                            listener.onSliding(1);//正负1
                        }
                    }
                }
                velocityTracker.clear();
                velocityTracker.recycle();
                break;
        }
        downY = y;
        return true;
    }

    int lastX, lastY;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                int dY = y - lastY;
                int dX = x - lastX;
                if (Math.abs(dY) > Math.abs(dX) && Math.abs(dY) > 0) {
                    return true;
                }
                break;
        }
        lastX = x;
        lastY = y;
        return super.onInterceptTouchEvent(ev);
    }

    public void open() {
        scroller.startScroll(0, menuHeight, 0, -menuHeight, 500);
        invalidate();
    }

    public void close() {
        scroller.startScroll(0, 0, 0, menuHeight, 500);
        invalidate();
    }

    public boolean isOpen() {
        return !(getScrollY() == menuHeight);
    }

    public interface OnSlidingListener {
        //0~1f
        void onSliding(float value);
    }
}
